<?php

use app\common\model\Config as ConfigModel;
use think\Exception;

// 公共助手函数

/*
 * 生成随机字符串
 * @param int $length 生成随机字符串的长度
 * @param string $char 组成随机字符串的字符串
 * @return string $string 生成的随机字符串
 */
function str_rand($length = 6) {
    $char = md5(uniqid(microtime(true),true));
    if(!is_int($length) || $length < 0) {
        return false;
    }
    $string = '';
    for($i = $length; $i > 0; $i--) {
        $string .= $char[mt_rand(0, strlen($char) - 1)];
    }
    return $string;
}

if (!function_exists('XEncode')) {

    /**
     * 数字加密
     */
    function XEncode($int,$length = 5)
    {
        if(!preg_match("/^[1-9][0-9]*$/",$int)) return false;
        $obj = new \easy\XDeode(5);
        return $obj->encode($int);
    }

}

if (!function_exists('XDecode')) {

    /**
     * 数字解密
     */
    function XDecode($string)
    {
        $length = strlen($string);
        $obj = new \easy\XDeode(5);
        return $obj->decode($string);
    }

}

if (!function_exists('configEdit')) {
    /**
    * 配置刷新
    */
    function configEdit($row){
        $configList = [];
        foreach (model('Config')->all() as $v) {
            if (isset($row[$v['name']])) {
                $value = $row[$v['name']];
                if (is_array($value) && isset($value['field'])) {
                    $value = json_encode(ConfigModel::getArrayData($value), JSON_UNESCAPED_UNICODE);
                } else {
                    $value = is_array($value) ? implode(',', $value) : $value;
                }
                $v['value'] = $value;
                $configList[] = $v->toArray();
            }
        }
        model('Config')->allowField(true)->saveAll($configList);
        $config = [];
        foreach (model('Config')->all() as $k => $v) {
            $value = $v->toArray();
            if (in_array($value['type'], ['selects', 'checkbox', 'images', 'files'])) {
                $value['value'] = explode(',', $value['value']);
            }
            if ($value['type'] == 'array') {
                $value['value'] = (array)json_decode($value['value'], TRUE);
            }
            $config[$value['name']] = $value['value'];
        }
        file_put_contents(APP_PATH . 'extra' . DS . 'site.php', '<?php' . "\n\nreturn " . var_export($config, true) . ";");
    }
}

if (!function_exists('QQTransfer')) {
    /**
    * qq个人转账
    */
    function QQTransfer($account,$money,$memo=''){
        if (!is_numeric($money) || $money.'' <= 0) return ['code'=>0,'msg'=>'最少一分钱'];
        $ch = curl_init();
        $path = EXTEND_PATH.DS.'pay'.DS.'qq_transfer_cert'.DS;
        $qqpayobj = new \pay\Qpay('https://api.qpay.qq.com/cgi-bin/epay/qpay_epay_b2c.cgi',true);
        $params = [
            'input_charset'=>'UTF-8',
            'uin'=>$account,
            'mch_id'=>config('site.qqpay_transfer_mchid'),
            'nonce_str'=>$qqpayobj->createNoncestr(),
            'out_trade_no'=>date("YmdHis").mt_rand(100,999),
            'fee_type'=>'CNY',
            'total_fee'=>(int)($money*100),
            'check_name'=>'false',
            're_user_name'=>'',
            'memo'=>$memo,
            'check_real_name'=>"0",
            'op_user_id'=>config('site.qqpay_transfer_userid'),
            'op_user_passwd'=>md5(config('site.qqpay_transfer_userpasswd')),
            'spbill_create_ip'=>request()->ip(),
        ];
        $params['sign'] = $qqpayobj->getSign($params,config('site.qqpay_transfer_key'));
        curl_setopt($ch,CURLOPT_URL, 'https://api.qpay.qq.com/cgi-bin/epay/qpay_epay_b2c.cgi');
        curl_setopt($ch,CURLOPT_TIMEOUT, 5);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch,CURLOPT_HEADER,FALSE);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT, $path.'apiclient_cert.pem');
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY, $path.'apiclient_key.pem');
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $qqpayobj->arrayToXml($params));
        $ret = curl_exec($ch);
        $xml = xml_parser($ret);
        if (!$xml) return ['code'=>0,'msg'=>'请检查代码和配置'];
        $data = xmlToArray($ret);
        if (isset($data['retcode']) && $data['retcode']=='0' && isset($data['result_code']) && $data['result_code']=='SUCCESS' && isset($data['nonce_str']) && $data['nonce_str']==$params['nonce_str']) {
            return ['code'=>1,'msg'=>'转账成功','payment_no'=>$data['transaction_id'],'payment_time'=>date('Y-m-d H:i:s',time())];
        }else{
            $msg = '转账失败 [ '.(isset($data['err_code'])?$data['err_code']:'未知').' ]'.(isset($data['err_code_desc'])?$data['err_code_desc']:'未知错误');
            return ['code'=>0,'msg'=>$msg];
        }
    }
}

if (!function_exists('AliTransfer')) {
    /**
    * 支付宝个人转账
    * @param $openid openid
    * @param $realname 真实姓名
    * @param $money 转账金额
    */
    function AliTransfer($account,$realname,$money){
        require_once(EXTEND_PATH."pay/alipay_transfer/lib/AopClient.php");
        require_once(EXTEND_PATH."pay/alipay_transfer/model/request/AlipayFundTransToaccountTransferRequest.php");
        $out_biz_no = date("Ymd").'000'.rand(111,999);
        $BizContent = array(
            'out_biz_no' => $out_biz_no, //商户转账唯一订单号
            'payee_type' => 'ALIPAY_LOGONID', //收款方账户类型
            'payee_account' => $account, //收款方账户
            'amount' => $money, //转账金额
            'payer_show_name' => config("site.alipay_transfer_name"),
            'payee_real_name' => $realname, //收款方真实姓名
            'remark'=>config("site.alipay_transfer_remark"),
        );
        $aop = new \AopClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = config("site.alipay_transfer_appid");
        $aop->rsaPrivateKey = config("site.alipay_transfer_privatekey");
        $aop->alipayrsaPublicKey=config("site.alipay_transfer_publickey");
        $aop->apiVersion = '1.0';
        $aop->signType = config("site.alipay_transfer_type");
        $aop->postCharset='UTF-8';
        $aop->format='json';
        $request = new \AlipayFundTransToaccountTransferRequest();
        $request->setBizContent(json_encode($BizContent));
        $result = $aop->execute ($request); 
        $data = '';
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode)&&$resultCode == 10000){
            return ['code'=>1,'msg'=>'OK','payment_no'=>$result->$responseNode->order_id,'payment_time'=>$result->$responseNode->pay_date];
        }else {
            $msg = '转账失败 [ '.(isset($result->$responseNode->sub_code)?$result->$responseNode->sub_code:'未知').' ]'.(isset($result->$responseNode->sub_msg) ? $result->$responseNode->sub_msg : '未知错误');
            return ['code'=>0,'msg'=>$msg];
        }
    }
}

if (!function_exists('WxTransfer')) {
    /**
    * 微信个人转账
    * @param $openid openid
    * @param $realname 真实姓名
    * @param $money 转账金额
    */
    function WxTransfer($openid,$realname,$money){
        $data = [];
        $out_biz_no = date("Ymd").'000'.rand(111,999);
        $Transfer = new \pay\wx\WxPayTransfer();
        $Transfer->SetPartner_trade_no($out_biz_no);
        $Transfer->SetOpenid($openid);
        $Transfer->SetCheck_name('FORCE_CHECK');
        $Transfer->SetRe_user_name($realname);
        $Transfer->SetAmount($money*100);
        $Transfer->SetDesc(config("site.wxtransfer_desc"));
        $Transfer->SetSpbill_create_ip($_SERVER['SERVER_ADDR']);
        $result = \pay\wx\WxPayApi::transfer($Transfer);
        if($result["result_code"]=='SUCCESS'){
            $data['code'] = 1;
            $data['msg'] = 'OK';
            $data['payment_no'] = $result["payment_no"];
            $data['payment_time'] = $result["payment_time"];
        }elseif($result["result_code"]=='FAIL' && ($result["err_code"]=='OPENID_ERROR'||$result["err_code"]=='NAME_MISMATCH'||$result["err_code"]=='MONEY_LIMIT'||$result["err_code"]=='V2_ACCOUNT_SIMPLE_BAN')) {
            $data['msg']='转账失败 ['.$result["err_code"].']'.$result["err_code_des"];
            $data['code'] = 0;
        }else{
            $data['code'] = 0;
            $data['msg'] = isset($result["err_code_des"])?$result["err_code_des"]:$result["return_msg"];
        }
        return $data;
    }
}

if (!function_exists('Pay')) {
    /**
    * 发起支付
    */
    function Pay($config = [],$e=true){
        $obj = new \pay\Easy();
        $url = str_replace('http://', '', config('site.pay_url'));
        $url = str_replace('https://', '', $url);
        $url = str_replace('/', '', $url);
        $url = 'http://'.$url.'/';
        $trade_no = date("YmdHis").mt_rand(100,999);
        $PayData = [
            'id' => config('site.pay_id'),
            'key' => config('site.pay_key'),
            'apiurl' => $url,
            'money' => isset($config['money']) ? $config['money'] : '999',
            'name' => isset($config['name']) ? $config['name'] : 'Pay',
            'type' => isset($config['type']) ? $config['type'] : 'wxpay',
            'notify_url' => isset($config['notify_url']) ? $config['notify_url']: request()->domain().'/notify',
            'return_url' => isset($config['return_url']) ? $config['return_url']: request()->domain().'/return',
            'trade_no' => $trade_no,
        ];
        if ($e) {
            $order = [
                'trade_no'=>$PayData['trade_no'],
                'type'=>$PayData['type'],
                'money'=>$PayData['money'],
                'config'=>isset($config['config']) ? $config['config'] : '',
                'title'=>isset($config['title']) ? $config['title'] : '',
                'uid'=>isset($config['uid']) ? $config['uid'] : '',
                'status'=>0,
                'createtime'=>time(),
            ];
            return json(['code'=>1,'msg'=>'OK','data'=>$obj->submit($PayData)]);
        }else{
            $obj->config($PayData);
            $data = $obj->verify_return();
            if ($data['code'] && $data['status']=='success') {
                return true;
            }else{
                $data = $obj->verify_notify();
                if ($data['code'] && $data['status']=='success') {
                    return true;
                }else{
                    return false;
                }
            }
        }
    }
}

if (!function_exists('ucpassSmsSend')) {
    /**
    * @param phone 手机号
    * @param param 短信模板参数
    */
    function ucpassSmsSend($params = []){
        if (!$params) return ['code'=>0,'msg'=>'信息不完整'];
        if (!isset($params['param']) || !isset($params['phone']) || !isset($params['templateid'])) {
            return ['code'=>0,'msg'=>'信息不完整'];
        }
        $config = [
            'appid'=>config('site.sms_id'),
            'templateid'=>$params['templateid'],
            'param'=>$params['param'],
            'phone'=>$params['phone'],
            'sid'=>config('site.sms_key'),
            'token'=>config('site.sms_token'),
        ];
        $obj = new \sms\ucpass\Ucpass();
        $data = $obj->submit($config);
        $sms = json_decode($data,true);
        if (!isset($sms['code']) || $sms['code'].''!=="000000") return ['code'=>0,'msg'=>isset($sms['msg'])?$sms['msg']:'发送失败'];
        return ['code'=>1,'msg'=>'发送成功'];
    }
}

if (!function_exists('orderEnd')) {
    /**
    * 支付后操作
    */
    function orderEnd($id,$get = [],$post = [],$verify = NULL,$status = false){
        $obj = model('PayOrder');
        $where = [];
        $status ? [] : $where['status'] = 0;
        $res = $obj->where(['id'=>$id])->where($where)->find();
        if (!$res) return ['code'=>0,'msg'=>'订单不存在！'];
        $buyer = '';
        if ($res['type_b'] == 'auth') {
            if ($res['type'] == 'alipay') {
                $buyer = isset($get['buyer_email']) ? $get['buyer_email'] : '';
            }elseif ($res['type'] == 'qqpay') {
                $buyer = isset($verify['openid']) ? $verify['openid'] : '';
            }elseif ($res['type'] == 'wxpay') {
                $buyer = isset($verify['openid']) ? $verify['openid'] : '';
            }
        }
        $status = db('pay_order')->where(['id'=>$res['id']])->find()['status'];
        if ($status !== 1) {
            $obj->where(['id'=>$id,'status'=>0])->update(['buyer'=>$buyer,'status'=>1,'updatetime'=>time()]);
            // 费率 加款 提成
            $user = model('User')->where(['id'=>$res['uid']])->find();
            if ($user) {
                $money = $user['money'];
              	if (!$res['charge']) {
                  $rate = is_numeric($user[$res['type'].'_rate']) ? $user[$res['type'].'_rate'] : config('site.default_'.$res['type'].'_rate');

                  $realmoney = round($res['money']*$rate/100,2);
                }else{
                    $rate = $res['rate'];
                    $realmoney = $res['realmoney'];
                }
                //真实金额/费率
                $obj->where(['id'=>$res['id']])->update(['realmoney'=>$realmoney,'rate'=>$rate]);
                //商户余额
                $prefix = config('database.prefix');
                \think\Db::execute("update {$prefix}user set money=money+{$realmoney} where id='{$res['uid']}'");

            }
            // 异步
            $array=[
                'pid'=>$user['api_id'],
                'trade_no'=>$res['trade_no'],
                'out_trade_no'=>$res['out_trade_no'],
                'type'=>$res['type'],
                'name'=>$res['title'],
                'money'=>($res['charge']?$res['realmoney']:$res['money']),
                'trade_status'=>'TRADE_SUCCESS'
            ];
            $arg = argSort(paraFilter($array));
            $prestr = createLinkstring($arg);
            $urlstr = createLinkstringUrlencode($arg);
            $sign = md5Sign($prestr, $user['api_key']);
            $n = strpos($res['notify_url'],'?') ? '&' : '?';
            $url = $res['notify_url'].$n.$urlstr.'&sign='.$sign.'&sign_type=MD5';
            getCurl(['url'=>$url,'type'=>'get']);
            // 同步
            $n = strpos($res['return_url'],'?') ? '&' : '?';
            $url = $res['return_url'].$n.$urlstr.'&sign='.$sign.'&sign_type=MD5';
            model("PayOrder")->where(['id'=>$res['id']])->update(['return_url_b'=>$url]);
            // 删除其他相同订单号订单
            model("PayOrder")->where(['out_trade_no'=>$res['out_trade_no'],'status'=>0])->delete();
            
            return ['code'=>1,'msg'=>'OK','url'=>$url];
        }
    }
}

if (!function_exists('getCurl')) {
    /**
    * curl
    */
    function getCurl($config){
        if (!isset($config['type'])) {
            $config['type'] = 'get';
        }
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $config['url']);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; GreenBrowser)');
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT , 10);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
        if ($config['type']=='get' || $config['type']=='GET') {
            $data = curl_exec($curl);
        }else{
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $config['param']);
            $data = curl_exec($curl);
        }
        curl_close($curl);
        return $data;
    }
}

if (!function_exists('EasyPay')) {
    /**
    * 发起支付
    */
    function EasyPay($config = [],$e=true){
        $obj = new \pay\Easy();
        $url = str_replace('http://', '', $config['apiurl']);
        $url = str_replace('https://', '', $url);
        $url = str_replace('/', '', $url);
        $url = 'http://'.$url.'/';
        $trade_no = date("YmdHis").mt_rand(100,999);
        $PayData = [
            'id' => $config['id'],
            'key' => $config['key'],
            'apiurl' => $url,
            'money' => isset($config['money']) ? $config['money'] : '999',
            'name' => isset($config['name']) ? $config['name'] : 'Pay',
            'type' => isset($config['type']) ? $config['type'] : 'wxpay',
            'notify_url' => isset($config['notify_url']) ? $config['notify_url'] : request()->domain().'/verify',
            'return_url' => isset($config['return_url']) ? $config['return_url'] : request()->domain().'/verify',
            'trade_no' => isset($config['trade_no']) ? $config['trade_no'] : $trade_no,
        ];
        if ($e) {
            return $obj->submit($PayData);
        }else{
            $obj->config($PayData);
            $data = $obj->verify_return();
            if ($data['code'] && $data['status']=='success') {
                return true;
            }else{
                $data = $obj->verify_notify();
                if ($data['code'] && $data['status']=='success') {
                    return true;
                }else{
                    return false;
                }
            }
        }
    }
}

if (!function_exists('get_api_info')) {
    /**
     * 添加不重复API信息
     */
    function get_api_info()
    {
        $obj = model('User');
        $api_id = mt_rand(100000,999999);
        $api_key = strtoupper(md5(uniqid()));
        $res = $obj->where(['api_id'=>$api_id])->find();
        if ($res) {
            get_api_info();
        }else{
            return ['api_id'=>$api_id,'api_key'=>$api_key];
        }

    }
}

if (!function_exists('PinYin')) {

    /**
     * 获取文字的拼音
     * @param string $chinese 中文汉字
     * @param boolean $onlyfirst 是否只返回拼音首字母
     * @param string $delimiter 分隔符
     * @param string $charset 文字编码
     * @return string
     */
    function PinYin($chinese, $onlyfirst = false, $delimiter = '', $ucfirst = false, $charset = 'utf-8')
    {
        return \fast\Pinyin::get($chinese, $onlyfirst, $delimiter, $ucfirst, $charset);
    }

}

if (!function_exists('__')) {

    /**
     * 获取语言变量值
     * @param string $name 语言变量名
     * @param array $vars 动态变量值
     * @param string $lang 语言
     * @return mixed
     */
    function __($name, $vars = [], $lang = '')
    {
        if (is_numeric($name) || !$name)
            return $name;
        if (!is_array($vars)) {
            $vars = func_get_args();
            array_shift($vars);
            $lang = '';
        }
        return \think\Lang::get($name, $vars, $lang);
    }

}

if (!function_exists('format_bytes')) {

    /**
     * 将字节转换为可读文本
     * @param int $size 大小
     * @param string $delimiter 分隔符
     * @return string
     */
    function format_bytes($size, $delimiter = '')
    {
        $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
        for ($i = 0; $size >= 1024 && $i < 6; $i++)
            $size /= 1024;
        return round($size, 2) . $delimiter . $units[$i];
    }

}

if (!function_exists('datetime')) {

    /**
     * 将时间戳转换为日期时间
     * @param int $time 时间戳
     * @param string $format 日期时间格式
     * @return string
     */
    function datetime($time, $format = 'Y-m-d H:i:s')
    {
        $time = is_numeric($time) ? $time : strtotime($time);
        return date($format, $time);
    }

}

if (!function_exists('human_date')) {

    /**
     * 获取语义化时间
     * @param int $time 时间
     * @param int $local 本地时间
     * @return string
     */
    function human_date($time, $local = null)
    {
        return \fast\Date::human($time, $local);
    }

}

if (!function_exists('cdnurl')) {

    /**
     * 获取上传资源的CDN的地址
     * @param string $url 资源相对地址
     * @param boolean $domain 是否显示域名 或者直接传入域名
     * @return string
     */
    function cdnurl($url, $domain = false)
    {
        $url = preg_match("/^https?:\/\/(.*)/i", $url) ? $url : \think\Config::get('upload.cdnurl') . $url;
        if ($domain && !preg_match("/^(http:\/\/|https:\/\/)/i", $url)) {
            if (is_bool($domain)) {
                $public = \think\Config::get('view_replace_str.__PUBLIC__');
                $url = rtrim($public, '/') . $url;
                if (!preg_match("/^(http:\/\/|https:\/\/)/i", $url)) {
                    $url = request()->domain() . $url;
                }
            } else {
                $url = $domain . $url;
            }
        }
        return $url;
    }

}


if (!function_exists('is_really_writable')) {

    /**
     * 判断文件或文件夹是否可写
     * @param    string $file 文件或目录
     * @return    bool
     */
    function is_really_writable($file)
    {
        if (DIRECTORY_SEPARATOR === '/') {
            return is_writable($file);
        }
        if (is_dir($file)) {
            $file = rtrim($file, '/') . '/' . md5(mt_rand());
            if (($fp = @fopen($file, 'ab')) === FALSE) {
                return FALSE;
            }
            fclose($fp);
            @chmod($file, 0777);
            @unlink($file);
            return TRUE;
        } elseif (!is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE) {
            return FALSE;
        }
        fclose($fp);
        return TRUE;
    }

}

if (!function_exists('rmdirs')) {

    /**
     * 删除文件夹
     * @param string $dirname 目录
     * @param bool $withself 是否删除自身
     * @return boolean
     */
    function rmdirs($dirname, $withself = true)
    {
        if (!is_dir($dirname))
            return false;
        $files = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST
        );

        foreach ($files as $fileinfo) {
            $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
            $todo($fileinfo->getRealPath());
        }
        if ($withself) {
            @rmdir($dirname);
        }
        return true;
    }

}

if (!function_exists('copydirs')) {

    /**
     * 复制文件夹
     * @param string $source 源文件夹
     * @param string $dest 目标文件夹
     */
    function copydirs($source, $dest)
    {
        if (!is_dir($dest)) {
            mkdir($dest, 0755, true);
        }
        foreach (
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST) as $item
        ) {
            if ($item->isDir()) {
                $sontDir = $dest . DS . $iterator->getSubPathName();
                if (!is_dir($sontDir)) {
                    mkdir($sontDir, 0755, true);
                }
            } else {
                copy($item, $dest . DS . $iterator->getSubPathName());
            }
        }
    }

}

if (!function_exists('mb_ucfirst')) {

    function mb_ucfirst($string)
    {
        return mb_strtoupper(mb_substr($string, 0, 1)) . mb_strtolower(mb_substr($string, 1));
    }

}

if (!function_exists('addtion')) {

    /**
     * 附加关联字段数据
     * @param array $items 数据列表
     * @param mixed $fields 渲染的来源字段
     * @return array
     */
    function addtion($items, $fields)
    {
        if (!$items || !$fields)
            return $items;
        $fieldsArr = [];
        if (!is_array($fields)) {
            $arr = explode(',', $fields);
            foreach ($arr as $k => $v) {
                $fieldsArr[$v] = ['field' => $v];
            }
        } else {
            foreach ($fields as $k => $v) {
                if (is_array($v)) {
                    $v['field'] = isset($v['field']) ? $v['field'] : $k;
                } else {
                    $v = ['field' => $v];
                }
                $fieldsArr[$v['field']] = $v;
            }
        }
        foreach ($fieldsArr as $k => &$v) {
            $v = is_array($v) ? $v : ['field' => $v];
            $v['display'] = isset($v['display']) ? $v['display'] : str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
            $v['primary'] = isset($v['primary']) ? $v['primary'] : '';
            $v['column'] = isset($v['column']) ? $v['column'] : 'name';
            $v['model'] = isset($v['model']) ? $v['model'] : '';
            $v['table'] = isset($v['table']) ? $v['table'] : '';
            $v['name'] = isset($v['name']) ? $v['name'] : str_replace(['_ids', '_id'], '', $v['field']);
        }
        unset($v);
        $ids = [];
        $fields = array_keys($fieldsArr);
        foreach ($items as $k => $v) {
            foreach ($fields as $m => $n) {
                if (isset($v[$n])) {
                    $ids[$n] = array_merge(isset($ids[$n]) && is_array($ids[$n]) ? $ids[$n] : [], explode(',', $v[$n]));
                }
            }
        }
        $result = [];
        foreach ($fieldsArr as $k => $v) {
            if ($v['model']) {
                $model = new $v['model'];
            } else {
                $model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
            }
            $primary = $v['primary'] ? $v['primary'] : $model->getPk();
            $result[$v['field']] = $model->where($primary, 'in', $ids[$v['field']])->column("{$primary},{$v['column']}");
        }

        foreach ($items as $k => &$v) {
            foreach ($fields as $m => $n) {
                if (isset($v[$n])) {
                    $curr = array_flip(explode(',', $v[$n]));

                    $v[$fieldsArr[$n]['display']] = implode(',', array_intersect_key($result[$n], $curr));
                }
            }
        }
        return $items;
    }

}

if (!function_exists('var_export_short')) {

    /**
     * 返回打印数组结构
     * @param string $var 数组
     * @param string $indent 缩进字符
     * @return string
     */
    function var_export_short($var, $indent = "")
    {
        switch (gettype($var)) {
            case "string":
                return '"' . addcslashes($var, "\\\$\"\r\n\t\v\f") . '"';
            case "array":
                $indexed = array_keys($var) === range(0, count($var) - 1);
                $r = [];
                foreach ($var as $key => $value) {
                    $r[] = "$indent    "
                        . ($indexed ? "" : var_export_short($key) . " => ")
                        . var_export_short($value, "$indent    ");
                }
                return "[\n" . implode(",\n", $r) . "\n" . $indent . "]";
            case "boolean":
                return $var ? "TRUE" : "FALSE";
            default:
                return var_export($var, TRUE);
        }
    }

}

if (!function_exists('camelize')) {
    /**
    * 下划线转驼峰
    */
    function camelize($uncamelized_words,$separator='_'){
        $uncamelized_words = $separator. str_replace($separator, " ", strtolower($uncamelized_words));
        return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator );
    }
}

if (!function_exists('uncamelize')) {
    /**
    * 驼峰命名转下划线命名
    */
    function uncamelize($camelCaps,$separator='_'){
        return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
    }
}








/**
 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstring($para) {
    $arg  = "";
    while (list ($key, $val) = each ($para)) {
        $arg.=$key."=".$val."&";
    }
    //去掉最后一个&字符
    $arg = substr($arg,0,count($arg)-2);
    
    //如果存在转义字符，那么去掉转义
    if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
    
    return $arg;
}
/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function paraFilter($para) {
    $para_filter = array();
    while (list ($key, $val) = each ($para)) {
        if($key == "sign" || $key == "sign_type" || $val == "")continue;
        else    $para_filter[$key] = $para[$key];
    }
    return $para_filter;
}
/**
 * 签名字符串
 * @param $prestr 需要签名的字符串
 * @param $key 私钥
 * return 签名结果
 */
function md5Sign($prestr, $key) {
    $prestr = $prestr . $key;
    return md5($prestr);
}

/**
 * 验证签名
 * @param $prestr 需要签名的字符串
 * @param $sign 签名结果
 * @param $key 私钥
 * return 签名结果
 */
function md5Verify($prestr, $sign, $key) {
    $prestr = $prestr . $key;
    $mysgin = md5($prestr);

    if($mysgin == $sign) {
        return true;
    }
    else {
        return false;
    }
}
/**
 * 对数组排序
 * @param $para 排序前的数组
 * return 排序后的数组
 */
function argSort($para) {
    ksort($para);
    reset($para);
    return $para;
}
/**
 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstringUrlencode($para) {
    $arg  = "";
    while (list ($key, $val) = each ($para)) {
        $arg.=$key."=".urlencode($val)."&";
    }
    //去掉最后一个&字符
    $arg = substr($arg,0,count($arg)-2);
    
    //如果存在转义字符，那么去掉转义
    if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
    
    return $arg;
}

/**
 * 写日志，方便测试（看网站需求，也可以改成把记录存入数据库）
 * 注意：服务器需要开通fopen配置
 * @param $word 要写入日志里的文本内容 默认值：空值
 */
function logResult($word='') {
    $fp = fopen("log.txt","a");
    flock($fp, LOCK_EX) ;
    fwrite($fp,"执行日期：".strftime("%Y%m%d%H%M%S",time())."\n".$word."\n");
    flock($fp, LOCK_UN);
    fclose($fp);
}

/**
 * 远程获取数据，POST模式
 * 注意：
 * 1.使用Crul需要修改服务器中php.ini文件的设置，找到php_curl.dll去掉前面的";"就行了
 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效，目前默认路径是：getcwd().'\\cacert.pem'
 * @param $url 指定URL完整路径地址
 * @param $cacert_url 指定当前工作目录绝对路径
 * @param $para 请求的数据
 * @param $input_charset 编码格式。默认值：空值
 * return 远程输出的数据
 */
function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = '') {

    if (trim($input_charset) != '') {
        $url = $url."_input_charset=".$input_charset;
    }
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL证书认证
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);//严格认证
    curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
    curl_setopt($curl,CURLOPT_POST,true); // post传输数据
    curl_setopt($curl,CURLOPT_POSTFIELDS,$para);// post传输数据
    $responseText = curl_exec($curl);
    //var_dump( curl_error($curl) );//如果执行curl过程中出现异常，可打开此开关，以便查看异常内容
    curl_close($curl);
    
    return $responseText;
}

/**
 * 远程获取数据，GET模式
 * 注意：
 * 1.使用Crul需要修改服务器中php.ini文件的设置，找到php_curl.dll去掉前面的";"就行了
 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效，目前默认路径是：getcwd().'\\cacert.pem'
 * @param $url 指定URL完整路径地址
 * @param $cacert_url 指定当前工作目录绝对路径
 * return 远程输出的数据
 */
function getHttpResponseGET($url,$cacert_url) {
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL证书认证
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);//严格认证
    $responseText = curl_exec($curl);
    //var_dump( curl_error($curl) );//如果执行curl过程中出现异常，可打开此开关，以便查看异常内容
    curl_close($curl);
    
    return $responseText;
}

/**
 * 实现多种字符编码方式
 * @param $input 需要编码的字符串
 * @param $_output_charset 输出的编码格式
 * @param $_input_charset 输入的编码格式
 * return 编码后的字符串
 */
function charsetEncode($input,$_output_charset ,$_input_charset) {
    $output = "";
    if(!isset($_output_charset) )$_output_charset  = $_input_charset;
    if($_input_charset == $_output_charset || $input ==null ) {
        $output = $input;
    } elseif (function_exists("mb_convert_encoding")) {
        $output = mb_convert_encoding($input,$_output_charset,$_input_charset);
    } elseif(function_exists("iconv")) {
        $output = iconv($_input_charset,$_output_charset,$input);
    } else die("sorry, you have no libs support for charset change.");
    return $output;
}
/**
 * 实现多种字符解码方式
 * @param $input 需要解码的字符串
 * @param $_output_charset 输出的解码格式
 * @param $_input_charset 输入的解码格式
 * return 解码后的字符串
 */
function charsetDecode($input,$_input_charset ,$_output_charset) {
    $output = "";
    if(!isset($_input_charset) )$_input_charset  = $_input_charset ;
    if($_input_charset == $_output_charset || $input ==null ) {
        $output = $input;
    } elseif (function_exists("mb_convert_encoding")) {
        $output = mb_convert_encoding($input,$_output_charset,$_input_charset);
    } elseif(function_exists("iconv")) {
        $output = iconv($_input_charset,$_output_charset,$input);
    } else die("sorry, you have no libs support for charset changes.");
    return $output;
}
/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function paraFilter2($para,$t = false) {
    foreach ($para as $k => $v) {
        if($k == "sign" || $k == "sign_type") {
            unset($para[$k]);
        }
    }
    return $para;
}
/**
 * 生成签名结果
 * @param $para_sort 已排序要签名的数组
 * return 签名结果字符串
 */
function buildRequestMysign($para_sort,$key) {
    //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
    $prestr = createLinkstring($para_sort);
    $mysign = md5($prestr.$key);
    return $mysign;
}

if (!function_exists('guolv')) {
    /**
     * 过滤脚本标签
     */
    function guolv($str){
        $key = [
            "<script>", 
            "<script", 
            "</script", 
            "</script>",
            "<style>", 
            "<style", 
            "</style", 
            "</style>",
            "<iframe>", 
            "<iframe", 
            "</iframe", 
            "</iframe>",
            "<head>", 
            "<head", 
            "</head", 
            "</head>",
            "<meta>", 
            "<meta", 
            "</meta", 
            "</meta>",
            "<link>", 
            "<link", 
            "</link", 
            "</link>",
            "<form>", 
            "<form", 
            "</form", 
            "</form>",
            "<applet>", 
            "<applet", 
            "</applet", 
            "</applet>",
            "<object>", 
            "<object", 
            "</object", 
            "</object>",
            "<noframes>", 
            "<noframes", 
            "</noframes", 
            "</noframes>",
            "<javascript>", 
            "<javascript", 
            "</javascript", 
            "</javascript>",
            "<vbscript>", 
            "<vbscript", 
            "</vbscript", 
            "</vbscript>",
            "<vbscript>", 
            "<vbscript", 
            "</vbscript", 
            "</vbscript>", 
            "onclick",
            "onchange",
            "<?php",
            "<?",
            "<?=",
            "<%",
            "<%=",
            "?>",
            "%>",
            ";?>",
            "{:",
            "}}",
        ];
        $value = [];
        for ($i=0; $i < count($key); $i++) { 
            $value[] = '';
        }
        $str = str_replace($key,$value,$str);
        return $str;
    }
}


function arrayToXml($arr)
{
    $xml = "<xml>";
    foreach ($arr as $key=>$val)
    {
        if (is_numeric($val)){
            $xml.="<".$key.">".$val."</".$key.">";
        }else{
             $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
    }
    $xml.="</xml>";
    return $xml;
}

function xmlToArray($xml)
{
    libxml_disable_entity_loader(true);
    $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $values;
}

function xml_parser($str){
    $xml_parser = xml_parser_create();
    if(!xml_parse($xml_parser,$str,true)){
      xml_parser_free($xml_parser);
      return false;
    }else {
      return (json_decode(json_encode(simplexml_load_string($str)),true));
    }
}